#include "WaitingWindow.h"

#include <QMessageBox>
#include <QMetaEnum>
#include <utility>

WaitingWindow::WaitingWindow(const QPair<QString, int>& address, QString name)
    : socket(new QTcpSocket(this))
    , name(std::move(name))
    , title_label(new QLabel("<h2>你画我猜大厅</h2>"
                             "<p>等待服务器开始游戏……</p>",
          this))
    , groupBox(new QGroupBox("玩家列表", this))
    , player_list(new QListWidget(this))
    , gridLayout(new QGridLayout(groupBox))
    , widget_layout(new QVBoxLayout(this))
{
    setWindowTitle("你画我猜大厅");
    setAttribute(Qt::WA_DeleteOnClose, true);

    title_label->setAlignment(Qt::AlignCenter);
    gridLayout->addWidget(player_list, 0, 0);
    widget_layout->addWidget(title_label);
    widget_layout->addWidget(groupBox);

    socket->connectToHost(address.first, address.second);

    connect(socket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
    connect(socket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)), this, SLOT(onErrorOccurred(QAbstractSocket::SocketError)));
}

void WaitingWindow::onReadyRead()
{
    auto msg = QString(socket->readAll());
    auto args = msg.split(' ');

    if (args[0] == "INIT") {
        // 游戏处于运行状态下无法开始游戏
        if (args[1] == "RUNNING") {
            QMessageBox::critical(this, "错误", "游戏已开始");
            this->close();
            return;
        }

        // 告诉服务器我是谁
        socket->write(QString("NAME %0").arg(name).toStdString().c_str());
        socket->waitForBytesWritten();
        // 添加自己
        player_list->addItem(name);
    } else if (args[0] == "QUIT") {
        this->close();
        return;
    } else if (args[0] == "JOIN") {
        auto name = args.mid(1).join(' ');
        player_list->addItem(name);
    } else if (args[0] == "LEAVE") {
        auto name = args.mid(1).join(' ');
        for (const auto& item : player_list->findItems(name, Qt::MatchExactly)) {
            qDebug() << "removeItemWidget";
            player_list->takeItem(player_list->row(item));
        }
    } else if (args[0] == "START") {
        disconnect(socket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
        disconnect(socket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)), this, SLOT(onErrorOccurred(QAbstractSocket::SocketError)));

        gameWindow = new GameWindow(socket);
        this->hide();
        gameWindow->show();

        connect(gameWindow, &GameWindow::closed, this, [=]() {
            emit closed();
        });
    }
}

#pragma clang diagnostic push
#pragma ide diagnostic ignored "readability-convert-member-functions-to-static"
void WaitingWindow::onErrorOccurred(QAbstractSocket::SocketError error)
{
    QMetaEnum e = QMetaEnum::fromType<QAbstractSocket::SocketError>();
    QMessageBox::critical(this, "错误", QString("网络错误 (错误信息：%0）").arg(e.valueToKey(error)));

    this->close();
}
#pragma clang diagnostic pop

void WaitingWindow::closeEvent(QCloseEvent* event)
{
    socket->close();
    this->hide();
    emit closed();
}